package net.htjs.juc.waitnotify;

import lombok.extern.slf4j.Slf4j;

import java.util.LinkedList;

@Slf4j
public class ProducerConsumerDemo {

    public static void main(String[] args) {
        MessageQueue queue = new MessageQueue(2);
        for(int i = 0; i < 3; i++) {
            int id = i;
            new Thread(() -> {
                log.info("{} 开始生产", Thread.currentThread().getName());
                queue.put(new Message(id, "msg:" + id));
                log.info("{} 生产完毕", Thread.currentThread().getName());
            }, "生产者" + i).start();
        }
            new Thread(() -> {
                while(true) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    log.info("{} 开始消费", Thread.currentThread().getName());
                    Message message = queue.take();
                    log.info("{} 消费完毕", Thread.currentThread().getName());
                }
            }, "消费者").start();
    }

    @Slf4j
    static class MessageQueue {
        private int capality;
        private LinkedList<Message> list = new LinkedList<>();

        public MessageQueue(int capality) {
            this.capality = capality;
        }

        public Message take() {
            synchronized (list) {
                while (list.isEmpty()) {
                    try {
                        list.wait();
                        log.info("队列为空，消费者线程等待");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                Message message = list.removeFirst();
                log.info("已消费了一个消息:{}",  message);
                list.notifyAll();
                return message;
            }
        }

        public void put(Message message) {
            synchronized (list) {
                //检查队列容量是否满了
                while (list.size() == capality) {
                    try {
                        list.wait();
                        log.info("队列已满，生产者线程等待");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                list.addLast(message);
                log.info("已生产了一个消息:{}",  message);
                list.notifyAll();
            }
        }
    }

    static final class Message {
        private int id;
        private String msg;

        public Message(int id, String msg) {
            this.id = id;
            this.msg = msg;
        }

        public int getId() {
            return id;
        }

        public String getMsg() {
            return msg;
        }
    }
}
